package roborally.model;

import roborally.model.interfaces.*;

/**
 * A class representing a Battery (inheriting from EnergyItem) with an energy-content and a weight
 * @Invar 	A battery always has a valid pair of energy and maxEnergy levels.
 * 			|EnergyAmount.isValidEnergy(getEnergy(),getMaxEnergy());
 * @Invar	|isValidWeight(getWeight())
 * @Extends EnergyItem
 * @Implements	Terminatable
 * @Implements	EnergyHolder
 */
public class Battery extends EnergyItem implements Terminatable, EnergyHolder{
	//CONSTRUCTOR
	/**
	 * Constructor of a Battery object
	 * @pre		
	 * 			|EnergyAmount.isValidEnergy(energy, getMaxEnergy())
	 * @param 	energy
	 * @param 	weight
	 * @effect	|super(initialEnergy, weight)
	 */
	public Battery(EnergyAmount initialEnergy, int weight) {
		super(weight, initialEnergy, EMAX_MAX);
		assert( EnergyAmount.isValidEnergy(initialEnergy, EMAX_MAX) );
	}
	/**
	 * Default constructor of a Battery object
	 * @effect	|this(EMAX_MAX, Item.WEIGHT_DEFAULT)
	 */
	public Battery(){
		this(EMAX_MAX, Item.WEIGHT_DEFAULT);
	}
	
	//Energy related
	/**
	 * An EnergyAmount object indicating the default maximum energylevel of a battery
	 */
	public static final EnergyAmount EMAX_MAX = new EnergyAmount(5000);
	/**
	 * An EnergyAmount expressing the increase in energy content a Battery can experience when it is hit by a robot's laser
	 */
	public static final EnergyAmount HIT_ENERGY = new EnergyAmount(500);
	
	//MUTATORS
	/**
	 * The effect a Battery experiences when it is hit by the laser of a Robot
	 * @effect If the energy content of the battery can be increased by HIT_ENERGY without exceeding getMaxEnergy(), it is done
	 * 		   | if(EnergyAmount.isValidEnergy(getEnergy().add(HIT_ENERGY), getMaxEnergy())) then
	 * 		   | setEnergy(getEnergy().add(HIT_ENERGY))
	 * @effect If the energy content of the battery cannot be increased by HIT_ENERGY without exceeding getMaxEnergy(), it is set at getMaxEnergy()
	 * 		   | if(!EnergyAmount.isValidEnergy(getEnergy().add(HIT_ENERGY), getMaxEnergy())) then
	 * 		   | setEnergy(getMaxEnergy())
	 */
	@Override
	public void hit() {
		if(EnergyAmount.isValidEnergy(getEnergy().add(HIT_ENERGY), getMaxEnergy())){
			this.setEnergy(getEnergy().add(HIT_ENERGY)); //The energycontent of the Battery can be increased by HIT_ENERGY
		}
		else {//The energycontent of the Battery cannot be increased by HIT_ENERGY because of overflow, we set it at getMaxEnergy()
			setEnergy(getMaxEnergy());
		}
	}
	
	//for inspecting in RoboRally main
	/**
	 * @return	A string indicating the field the battery object is placed on, whether or not it is terminated,
	 * 			its energycontent and its maximum energy. If the battery is not on any board, "not on board" is returned.
	 */
	@Override
	public String toString(){
		String sfield;
		if(isPlacedOnBoard()) sfield = getField().toString();
		else sfield = "not on board";
		return "Battery on field: " + sfield + "| terminated: " + isTerminated()+"| energy: "+getEnergy().toUnit(EnergyUnit.WS).getAmount()+"Ws/(max)"+getMaxEnergy().toUnit(EnergyUnit.WS).getAmount() + "Ws | weight: "+getWeight()+"g";
	}
}
